#include "iot_service.h"
#include <stdio.h>
#include <stdlib.h>
#include <libubus.h>
#include <libubox/uloop.h>
#include <libubox/list.h>
#include <libubox/blobmsg_json.h>
#include <cjson/cJSON.h>
#include "comm.h"
#include "data_type.h"
#include "trans_util.h"


extern t_RunCfg runCfg;
struct blob_buf ib;

static const struct blobmsg_policy ports_policy[] = {
    [0] = { .name = "lan1", .type = BLOBMSG_TYPE_TABLE },
    [1] = { .name = "lan2", .type = BLOBMSG_TYPE_TABLE },
    [2] = { .name = "lan3", .type = BLOBMSG_TYPE_TABLE },
    [3] = { .name = "lan4", .type = BLOBMSG_TYPE_TABLE },
    [4] = { .name = "wan",  .type = BLOBMSG_TYPE_TABLE },
};

static const struct blobmsg_policy netdev_policy[] = {
    [0] = { .name = "up",           .type = BLOBMSG_TYPE_BOOL },
    [1] = { .name = "speed",        .type = BLOBMSG_TYPE_STRING },
    [2] = { .name = "statistics",   .type = BLOBMSG_TYPE_TABLE },
};
static const struct blobmsg_policy statistics_policy[] = {
    [0] = { .name = "rx_bytes",     .type = BLOBMSG_TYPE_INT64 },
    [1] = { .name = "tx_bytes",     .type = BLOBMSG_TYPE_INT64 },
    [2] = { .name = "rx_packets",   .type = BLOBMSG_TYPE_INT64 },
    [3] = { .name = "tx_packets",   .type = BLOBMSG_TYPE_INT64 },
};
/**
 * 解析端口状态数据
 */
static void parse_port_data(struct blob_attr *msg, cJSON *json){
    struct blob_attr *tb_netdev[3], *tb_statistics[4];
    blobmsg_parse(netdev_policy, ARRAY_SIZE(netdev_policy), tb_netdev, blobmsg_data(msg), blobmsg_data_len(msg));
    if(tb_netdev[0]){
        bool up = blobmsg_get_bool(tb_netdev[0]);
        EP_JSON_SET_BOOL(json, "up", up);
    }
    
    if(tb_netdev[1]){
        char *speed = blobmsg_get_string(tb_netdev[1]);
        EP_JSON_SET_STR(json, "speed", speed);
    }else{
        EP_JSON_SET_STR(json, "speed", "0");
    }
    
    if(tb_netdev[2]){
        blobmsg_parse(statistics_policy, ARRAY_SIZE(statistics_policy), tb_statistics, blobmsg_data(tb_netdev[2]), blobmsg_data_len(tb_netdev[2]));
        if(tb_statistics[0]){
            uint64_t rx_bytes = blobmsg_get_u64(tb_statistics[0]);
            EP_JSON_SET_INT(json,"rx_bytes",rx_bytes);
        }
        if(tb_statistics[1]){
            uint64_t tx_bytes = blobmsg_get_u64(tb_statistics[1]);
            EP_JSON_SET_INT(json,"tx_bytes",tx_bytes);
        }
        if(tb_statistics[2]){
            uint64_t rx_packets = blobmsg_get_u64(tb_statistics[2]);
            EP_JSON_SET_INT(json,"rx_packets",rx_packets);
        }
        if(tb_statistics[2]){
            uint64_t tx_packets = blobmsg_get_u64(tb_statistics[3]);
            EP_JSON_SET_INT(json,"tx_packets",tx_packets);
        }
    }
    
}
/**
 * 获取端口状态数据
 */
static void ports_callback(struct ubus_request *req, int type, struct blob_attr *msg) {

    if (!msg) {
        return;
    }
    cJSON *portInfo = (cJSON *)req->priv;
    // 解析内存数据
    struct blob_attr *tb[5];
    blobmsg_parse(ports_policy, ARRAY_SIZE(ports_policy), tb, blobmsg_data(msg), blobmsg_data_len(msg));
    if (tb[0]) {
        cJSON *lan1 = cJSON_CreateObject();
        parse_port_data(tb[0], lan1);
        cJSON_AddItemToObject(portInfo,"lan1",lan1);
    }
    if (tb[1]) {
        cJSON *lan2 = cJSON_CreateObject();
        parse_port_data(tb[1], lan2);
        cJSON_AddItemToObject(portInfo,"lan2",lan2);
    }
    if (tb[2]) {
        cJSON *lan3 = cJSON_CreateObject();
        parse_port_data(tb[2], lan3);
        cJSON_AddItemToObject(portInfo,"lan3",lan3);
    }
    if (tb[3]) {
        cJSON *lan4 = cJSON_CreateObject();
        parse_port_data(tb[3], lan4);
        cJSON_AddItemToObject(portInfo,"lan4",lan4);
    }
    if (tb[4]) {
        cJSON *wan = cJSON_CreateObject();
        parse_port_data(tb[4], wan);
        cJSON_AddItemToObject(portInfo,"wan",wan);
    }
    // char *str = cJSON_Print(ports);
    // printf("%s\n", str);
    // mqtt_send_data(str);
    // cJSON_Delete(ports);
}

/**获取内存数据 */
static const struct blobmsg_policy system_info_policy[] = {
    [0] = { .name = "memory",     .type = BLOBMSG_TYPE_TABLE },
    [1] = { .name = "localtime",     .type = BLOBMSG_TYPE_INT32 },
    [2] = { .name = "uptime",     .type = BLOBMSG_TYPE_INT32 },
};
static const struct blobmsg_policy memory_policy[] = {
    [0] = { .name = "total",     .type = BLOBMSG_TYPE_INT64 },
    [1] = { .name = "free",     .type = BLOBMSG_TYPE_INT64 },
};
/**
 * 获取内存数据
 */
static void memory_callback(struct ubus_request *req, int type, struct blob_attr *msg) {
    if (!msg) return;
    cJSON *statusData = (cJSON *)req->priv;
    // 解析内存数据
    struct blob_attr *tb[3];
    blobmsg_parse(system_info_policy,  ARRAY_SIZE(system_info_policy), tb, blobmsg_data(msg), blobmsg_data_len(msg));
    if(tb[0]){
        struct blob_attr *tb_memory[2];
        blobmsg_parse(memory_policy, ARRAY_SIZE(memory_policy), tb_memory, blobmsg_data(tb[0]), blobmsg_data_len(tb[0]));
        if (tb_memory[0] && tb_memory[1]) {
            uint64_t total = blobmsg_get_u64(tb_memory[0]);
            uint64_t free = blobmsg_get_u64(tb_memory[1]);
            uint64_t used = total - free;
            int usage = (used * 100) / total;
            EP_JSON_SET_INT(statusData,"memory",usage);
            printf("Memory Usage: %d%%\n", usage);
        }
    }
    if(tb[1]){
        uint32_t localtime = blobmsg_get_u32(tb[1]);
        EP_JSON_SET_INT(statusData,"localtime",localtime);
    }
    if(tb[2]){
        uint32_t uptime = blobmsg_get_u32(tb[2]);
        EP_JSON_SET_INT(statusData,"uptime",uptime);
    }
}

/**读取CPU状态数据 */
static void read_cpu_stats(unsigned long long *total, unsigned long long *idle) {
    unsigned long long user, nice, system; // 声明变量
    FILE *fp = fopen("/proc/stat", "r");
    fscanf(fp, "cpu %llu %llu %llu %llu", &user, &nice, &system, idle);
    *total = user + nice + system + *idle;
    fclose(fp);
}

int read_cpu() {
    unsigned long long total1, idle1, total2, idle2;
    read_cpu_stats(&total1, &idle1);
    sleep(1);
    read_cpu_stats(&total2, &idle2);

    unsigned long long total = total2 - total1;
    unsigned long long idle = idle2 - idle1;
    int usage = ((total - idle) * 100) / total;
    // EP_JSON_SET_INT(statusData,"cpu",usage);
    printf("CPU Usage: %d%%\n", usage);
    return usage;
}
/**获取内存数据 */
static const struct blobmsg_policy location_policy[] = {
    [0] = { .name = "latitude",     .type = BLOBMSG_TYPE_STRING },
    [1] = { .name = "longitude",    .type = BLOBMSG_TYPE_STRING },
    [2] = { .name = "altitude",     .type = BLOBMSG_TYPE_STRING },
};
/**
 * 获取定位数据
 */
static void location_callback(struct ubus_request *req, int type, struct blob_attr *msg) {
    if (!msg) return;
    cJSON *statusData = (cJSON *)req->priv;
    // 解析内存数据
    struct blob_attr *tb[3];
    blobmsg_parse(location_policy,  ARRAY_SIZE(location_policy), tb, blobmsg_data(msg), blobmsg_data_len(msg));
    if(tb[0]){
        char *latitude = blobmsg_get_string(tb[0]);
        EP_JSON_SET_STR(statusData,"latitude",latitude);
    }
    if(tb[1]){
        char *longitude = blobmsg_get_string(tb[1]);
        EP_JSON_SET_STR(statusData,"longitude",longitude);
    }
    if(tb[2]){
        char *altitude = blobmsg_get_string(tb[2]);
        EP_JSON_SET_STR(statusData,"altitude",altitude);
    }
}

int read_iot_status_data() {

    cJSON *root = cJSON_CreateObject();
    EP_JSON_SET_STR(root, "sn", runCfg.sn);
    EP_JSON_SET_INT(root, "loraId", runCfg.lora_addr);
    EP_JSON_SET_INT(root, "dataType", 0);
    EP_JSON_SET_INT(root, "version", 1);
    char modelNumber[50] = {0};
    cJSON *iotData = cJSON_CreateObject();
    EP_JSON_SET_STR(iotData, "workTime", runCfg.work_time);
    EP_JSON_SET_STR(iotData, "sleepTime", runCfg.sleep_time);
    EP_JSON_SET_INT(iotData, "loraTrans", runCfg.lora_trans);
    EP_JSON_SET_INT(iotData, "loraGroup", runCfg.lora_group);
    EP_JSON_SET_STR(iotData, "loraVersion", "0.1.8");
    EP_JSON_SET_INT(iotData, "loraModel", 3);
    EP_JSON_SET_INT(iotData, "loraTxPower", 30);
    //sprintf(modelNumber, "%s_BD_1", runCfg.sn);
    //EP_JSON_SET_STR(iotData, "modelNumber", modelNumber);

    cJSON *statusData = cJSON_CreateObject();
    cJSON *portInfo = cJSON_CreateObject();
    // 连接 ubus
    struct ubus_context *ctx = ubus_connect(NULL);
    if (!ctx) {
        fprintf(stderr, "Failed to connect to ubus\n");
        return -1;
    }
    // 查找 network.device 的 ID
    uint32_t obj_id;
    if (ubus_lookup_id(ctx, "network.device", &obj_id) != 0) {
        fprintf(stderr, "Failed to lookup network.device\n");
        ubus_free(ctx);
        return -1;
    }
    // 准备请求参数（指定接口名，如 eth0）
    // struct blob_buf b;
    blob_buf_init(&ib, 0);
    // blobmsg_add_string(&b, "name", "eth0");  // 可替换为其他接口名
    // 发起异步调用
    int ret = ubus_invoke(ctx, obj_id, "status", ib.head, ports_callback, (void *)portInfo, 3000);
    if (ret != 0) {
        fprintf(stderr, "ubus_invoke failed: %s\n", ubus_strerror(ret));
    }
    sleep(1);
    ubus_lookup_id(ctx, "system", &obj_id);
    ret = ubus_invoke(ctx, obj_id, "info", NULL, memory_callback, (void *)iotData, 1000);
    if (ret != 0) {
        fprintf(stderr, "memony ubus_invoke failed: %s\n", ubus_strerror(ret));
    }
    sleep(1);
    ubus_lookup_id(ctx, "sihan.beidou", &obj_id);
    ret = ubus_invoke(ctx, obj_id, "location", NULL, location_callback, (void *)iotData, 1000);
    if (ret != 0) {
        fprintf(stderr, "location ubus_invoke failed: %s\n", ubus_strerror(ret));
    }
    sleep(1);
    int usage = read_cpu();
    EP_JSON_SET_INT(iotData,"cpu",usage);

    // cJSON_AddItemToObject(iotData,"statusData",statusData);
    cJSON_AddItemToObject(iotData,"ports",portInfo);
    cJSON_AddItemToObject(root,"data",iotData);
    char *str = cJSON_Print(root);
    printf("%s\n", str);
    send_data_to_mqtt(str);
    
    cJSON_Delete(root);
    // 清理资源
    blob_buf_free(&ib);
    ubus_free(ctx);
    return 0;
}

//接收LoRa数据的线程
void *iot_worker(void *param)
{
    while (1)
    {
        read_iot_status_data();
        sleep(5 * 60);
    }
}

int iot_worker_start() {
    if(runCfg.iot_enable){
        pthread_t pid;
        pthread_create(&pid, NULL, (void *)iot_worker, NULL);
    }
}

